/*
 * File:    Sql.java
 * Created: 24-Feb-2009
 * Version: $Id$
 *
 * COPYRIGHT (C) 2009, Bitgate Mobile, LLC.  All Rights Reserved.
 *
 * software@bitgatemobile.com
 */

package com.webplasm.render.tags.u;

import static com.bitgate.util.debug.Debug.debug;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.List;

import com.bitgate.util.sql.Registry;
import com.webplasm.context.RenderContext;
import com.webplasm.render.engine.RenderException;
import com.webplasm.render.tags.TagInterface;
import com.webplasm.render.tags.WrappedNode;
import com.webplasm.store.VariableStoreInterface;
import com.webplasm.store.VariableContainer.VariableType;

/**
 * Provides a simple way to perform a SQL statement.
 * 
 * @author kenji
 * @since Webplasm 1.0
 */
public class Sql extends WrappedNode implements TagInterface {
	private static final String DESCRIPTION = "Performs a SQL query.";

	public String getNamespace() {
		return "u";
	}
	
	public List<String> getAttributes() {
		return Arrays.asList("var", "pool");
	}
	
	public List<String> getManagedNodes() {
		return null;
	}

	public String getDescription() {
		return DESCRIPTION;
	}

	@Override
	public StringBuffer render(RenderContext rContext) throws RenderException {
		if (elements.get("pool") == null) {
			throw new RenderException("u:sql requires a pool to use.");
		}

		StringBuffer buf = super.render(rContext);
		Connection conn = Registry.getDefault().get(elements.get("pool"));
		
		if (conn == null) {
			debug("u:sql cannot retrieve pool by name '" + elements.get("pool") + "': null returned.");
			throw new RenderException("u:sql requests pool '" + elements.get("pool") + "' that doesn't exist or may be down.");
		}
		
		Statement stmt = null;
		
		try {
			stmt = conn.createStatement();
		} catch(SQLException ex) {
			debug("u:sql cannot create statement to pool '" + elements.get("pool") + "': " + ex.getMessage());
			throw new RenderException("u:sql exception: cannot create statement for pool '" + elements.get("pool") + "'");
		}
		
		ResultSet rSet = null;
		int numResults = 0;
		
		try {
			String sqlQuery = buf.toString();
			
			if (sqlQuery != null && sqlQuery.length() > 6) {
				if (sqlQuery.substring(0, 6).equalsIgnoreCase("select")) {
					debug("Executing with executeQuery: Statement='" + sqlQuery + "'");
					rSet = stmt.executeQuery(buf.toString());
				} else {
					debug("Executing with executeUpdate: Statement='" + sqlQuery + "'");
					numResults = stmt.executeUpdate(sqlQuery);
				}
			}
		} catch(SQLException ex) {
			debug("u:sql cannot execute query on pool '" + elements.get("pool") + "': " + ex.getMessage());
			throw new RenderException("u:sql exception: cannot execute query on pool '" + elements.get("pool") + "'");
		}
		
		if (elements.get("var") != null) {
			VariableStoreInterface vsInterface = null;

			try {
				if (rSet != null) {
					debug("Setting result: " + rSet.getFetchSize() + " result(s)");
					
					vsInterface = rContext.getVariableStore().getVariable(elements.get("var"), VariableType.SQL);
					vsInterface.setValue(rSet);
				} else if (numResults != 0) {
					debug("Setting result (number of columns): " + numResults);
					
					vsInterface = rContext.getVariableStore().getVariable(elements.get("var"), VariableType.INTEGER);
					vsInterface.setValue("" + numResults);
				}
			} catch(SQLException ex) {
				debug("Exception trying to get the number of rows returned.");
			}
		}
			
		return new StringBuffer();
	}
}